<?php
namespace Plu\Library\Services\RPC;

use Plu\Library\Services\ServiceBase,
    Thrift\Transport\TStreamSocketPool,
    Thrift\Transport\TFramedTransport,
    Thrift\Protocol\TCompactProtocol,
    Thrift\Service\ThriftServerClient,
    Thrift\Service\Request,
    Phalcon\Config;

/**
 * 
 * $client = new ClientService(array(
 *     '172.16.9.117:29090',
 * ));
 * $client->setServer('go.micro.srv.follow');
 * 
 * $responseObj = $client->setMethod('Follow.Stars')->setParams(array(
 *     "toUserID" => 20882022
 * ))->read();
 *
 */
class ClientService extends ServiceBase {
    private $_client;

    private $_request;

    /**
     * @param array $servers RPC服务器组
     * @param bool  $persist 是否开启长连，默认关闭
     */
    public function __construct($servers, $persist=false) {
        if ($servers instanceof Config) {
            $servers = $servers->toArray();
        }

        if (!is_array($servers)) {
            $servers = [$servers];
        }

        $socket = new TStreamSocketPool($servers, $persist);
        $socket->setRecvTimeout(10 * 1000);

        $transport = new TFramedTransport($socket, 1024, 1024);
        $protocol = new TCompactProtocol($transport);
        $client = new ThriftServerClient($protocol);

        $transport->open();

        $this->_client = $client;
        $this->_request = new Request();
    }

    public function setHeader($header) {
        $this->_request->header = $header;
        return $this;
    }

    public function setServer($server) {
        $this->_request->server = $server;
        return $this;
    }

    public function getServer() {
        return $this->_request->server;
    }

    public function setMethod($method) {
        $this->_request->method = $method; 
        return $this;
    }

    public function setParams($params = array()) {
        $params = json_encode($params);
        $this->_request->body = $params;
        return $this;
    }

    public function read() {
        try {
            $this->response = $this->_client->Call($this->_request);
            if ($this->response->code != 0) {
                throw new \Exception("Failed on RPC CALL, REQUEST: " . json_encode($this->_request) . '; RESPONSE:' . json_encode($this->response));
            }
        } catch (\Exception $e) {
            $error = sprintf("current request: service: `%s`, header: `%s`, method: `%s`, body: `%s` \n %s", $this->_request->server, json_encode($this->_request->header), $this->_request->method, $this->_request->body, $e);
            throw new \Exception($error);
        }

        return $this;
    }

    public function getCode() {
        if (!$this->response) {
            return;
        }

        return $this->response->getCode();
    }

    public function getData($assoc = true) {
        return $this->response->getData($assoc);
    }
}
